#ifndef ATLAS_H
#define ATLAS_H

#include "Map.h"
#include "KeyPoseFrame.h"
#include "Viewer.h"

#include <set>
#include <mutex>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/export.hpp>

namespace msf
{
class Viewer;
class Map;
class KeyPoseFrame;
class PoseFrame;

class Atlas
{
      // 1. 对boost声明友元，boost就能调用Atlas的serialize了
      friend class boost::serialization::access;

      // 保存读取都用这个
      template<class Archive>
      void serialize(Archive &ar, const unsigned int version)
      {
            // 由于保存相机是基类，但是实际使用是派生类，所以声明一下
            //ar.template register_type<Pinhole>();
            //ar.template register_type<KannalaBrandt8>();

            // Save/load a set structure, the set structure is broken in libboost 1.58 for ubuntu 16.04, a vector is serializated
            //ar & mspMaps;
            // 基础类型不用管，但是自定义的类里面要进一步写serialize函数，确定保存内容
            ar & mvpBackupMaps;
            // Need to save/load the static Id from Frame, KeyFrame, MapPoint and Map
            ar & Map::nNextId;
            ar & PoseFrame::nNextId;
            ar & KeyPoseFrame::nNextId;
      }

public:
      EIGEN_MAKE_ALIGNED_OPERATOR_NEW

      Atlas();
      Atlas(int initKPFid); // When its initialization the first map is created
      ~Atlas();

      void CreateNewMap();
      void ChangeMap(Map* pMap);

      unsigned long int GetLastInitKPFid();

      void SetViewer(Viewer* pViewer);

      // Method for change components in the current map
      void AddKeyPoseFrame(KeyPoseFrame* pKPF);

      /* All methods without Map pointer work on current map */
      void InformNewBigChange();
      int GetLastBigChangeIdx();

      long unsigned KeyPoseFramesInMap();

      // Method for get data in current map
      std::vector<KeyPoseFrame*> GetAllKeyPoseFrames();
      std::vector<Map*> GetAllMaps();

      int CountMaps();

      void clearMap();

      void clearAtlas();

      Map* GetCurrentMap();

      void SetMapBad(Map* pMap);
      void RemoveBadMaps();

      bool isInertial();
      void SetInertialSensor();
      void SetImuInitialized();
      bool isImuInitialized();

      // Function for garantee the correction of serialization of this object
      void PreSave();
      void PostLoad();

      std::map<long unsigned int, KeyPoseFrame*> GetAtlasKeyPoseframes();

protected:

      std::set<Map*> mspMaps;
      std::set<Map*> mspBadMaps;

      std::vector<Map*> mvpBackupMaps;

      Map* mpCurrentMap;

      unsigned long int mnLastInitKPFidMap;

      Viewer* mpViewer;
      bool mHasViewer;

      // Mutex
      std::mutex mMutexAtlas;

}; // class Atlas

} // namespace msf

#endif // ATLAS_H